package br.ufal.ic.ml;

public abstract class Simulation {
	private Agent agent;
	private Environment environment;
	private Sensation sensation;
	private Action action;
	private Sensation TERMINAL_STATE;

	public Simulation(Agent agent, Environment environment) {
		this.agent = agent;
		this.environment = environment;
		sensation = null;
		action = null;
	}

	public void init(int argc, char argv[]) {
		//Inicializar agente e ambiente
	}

	
	//Executar apenas suma vez
	public void steps(long num_steps) {
	    Sensation nextSensation = null;
	    Action    nextAction;
		double reward = 0;

	    if ( sensation == TERMINAL_STATE ) {
	        start_trial();
	    }
	    
	    for(long step = 0; step < num_steps ; step++) {

	        environment.step( action, nextSensation, reward );
	        
	        collect_data( sensation, action, nextSensation, reward );// Grava no arquivo os dados
	        
	        nextAction = agent.step( nextSensation, reward );
	        
	        if (nextSensation != TERMINAL_STATE) {
	            sensation = nextSensation;
	            action = nextAction;
	        } else {
	            start_trial();
	        }
	    }

	}

	public void trials(long num_trials, long max_steps_per_trial) {
		Sensation nextSensation = null;
	    Action    nextAction;
		double reward = 0;
	    long      trial;
	    long      step;

	    if (sensation == TERMINAL_STATE ){
	        start_trial();
	    }
	    
	    for(trial = 0 ; trial < num_trials ; trial++) {
	        for( step = 0; (sensation != null) && (step < max_steps_per_trial) ; step++) {
	            
	            environment.step(action, nextSensation, reward); //Passa action e o metodo atualisa nextSensation e reward
	        
	            collect_data(sensation, action, nextSensation, reward);

	            nextAction = agent.step(nextSensation, reward);

	            sensation = nextSensation;
	            action= nextAction;
	        }

	        start_trial();
	    }

	}

	public void start_trial() {
		sensation = environment.start_trial();
	    action = agent.start_trial(sensation);

	}

	public abstract void collect_data(Sensation sensation, Action action,
			Sensation nextSensation, double reward);
}
